package org.jf.tool.fx.jftoolfx.encrypt.controller;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import org.jf.tool.fx.jftoolfx.common.BaseController;
import org.jf.tool.fx.jftoolfx.util.SymmetricUtil;

import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HexFormat;
import java.util.ResourceBundle;

/**
 * 对称加解密
 *
 * @author jifeng_zhang
 * @date 2025/8/18 下午2:16
 */
public class SymmetricController extends BaseController {
    @FXML
    public ToggleGroup typeGroup;
    @FXML
    public ToggleGroup modeGroup;
    @FXML
    public ToggleGroup ivGroup;
    @FXML
    public Label ivLabelType;
    @FXML
    public RadioButton ivRadio;
    @FXML
    public HBox ivBox;
    @FXML
    public Label ivLabelValue;
    @FXML
    public TextField ivText;
    @FXML
    public ComboBox paddingBox;
    @FXML
    public TextField keyText;
    @FXML
    public ToggleGroup plainGroup;
    @FXML
    public TextArea plainText;
    @FXML
    public TextField filePathField;
    @FXML
    public HBox fileBox;
    @FXML
    public ToggleGroup resultGroup;
    @FXML
    public TextArea resultArea;
    @FXML
    public HBox modeHBox;
    @FXML
    public HBox paddingHBox;


    @Override
    protected void init(URL url, ResourceBundle resourceBundle) {

    }

    public void encrypt(ActionEvent actionEvent) {
        try {
            String typeName = typeGroup.getSelectedToggle().getUserData().toString();
            String modeName = modeGroup.getSelectedToggle().getUserData().toString();
            String ivType = ivGroup.getSelectedToggle().getUserData().toString();
            String plainType = plainGroup.getSelectedToggle().getUserData().toString();
            String keyStr = keyText.getText();
            String plainStr = plainText.getText();
            String iv = ivText.getText();
            if ("plain".equalsIgnoreCase(ivType)) {
                iv = Base64.getEncoder().encodeToString(iv.getBytes(StandardCharsets.UTF_8));
            }
            String paddingName = paddingBox.getValue().toString();
            SymmetricUtil.TYPE type = SymmetricUtil.getType(typeName);
            SymmetricUtil.MODE mode = SymmetricUtil.getMode(modeName);
            SymmetricUtil.PADDING padding = SymmetricUtil.getPadding(paddingName);
            if (type == null || mode == null || padding == null) {
                resultArea.setText("参数不合法！");
                return;
            }
            if (keyStr == null || keyStr.isEmpty()) {
                resultArea.setText("请输入密钥！");
                return;
            }
            if (plainStr == null || plainStr.isEmpty()) {
                resultArea.setText("请输入原文！");
                return;
            }
            byte[] plain = plain2Byte(plainType, plainStr);
            byte[] result = SymmetricUtil.encrypt(type, keyText.getText(), plain, mode, iv, padding);
            String resultType = resultGroup.getSelectedToggle().getUserData().toString();
            if ("base64".equalsIgnoreCase(resultType)) {
                resultArea.setText(Base64.getEncoder().encodeToString(result));
            } else if ("hex".equalsIgnoreCase(resultType)) {
                resultArea.setText(HexFormat.of().formatHex(result).toUpperCase());
            } else {
                resultArea.setText(new String(result));
            }
        } catch (Exception e) {
            resultArea.setText("加密失败：" + e.getMessage());
        }
    }

    public void decrypt(ActionEvent actionEvent) {
        try {
            String typeName = typeGroup.getSelectedToggle().getUserData().toString();
            String modeName = modeGroup.getSelectedToggle().getUserData().toString();
            String ivType = ivGroup.getSelectedToggle().getUserData().toString();
            String plainType = plainGroup.getSelectedToggle().getUserData().toString();
            String keyStr = keyText.getText();
            String plainStr = plainText.getText();
            String iv = ivText.getText();
            if ("plain".equalsIgnoreCase(ivType)) {
                iv = Base64.getEncoder().encodeToString(iv.getBytes(StandardCharsets.UTF_8));
            }
            String paddingName = paddingBox.getValue().toString();
            SymmetricUtil.TYPE type = SymmetricUtil.getType(typeName);
            SymmetricUtil.MODE mode = SymmetricUtil.getMode(modeName);
            SymmetricUtil.PADDING padding = SymmetricUtil.getPadding(paddingName);
            if (type == null || mode == null || padding == null) {
                resultArea.setText("参数不合法！");
                return;
            }
            if (keyStr == null || keyStr.isEmpty()) {
                resultArea.setText("请输入密钥！");
                return;
            }
            if (plainStr == null || plainStr.isEmpty()) {
                resultArea.setText("请输入原文！");
                return;
            }
            byte[] plain = plain2Byte(plainType, plainText.getText());
            byte[] result = SymmetricUtil.decrypt(type, keyText.getText(), plain, mode, iv, padding);
            String resultType = resultGroup.getSelectedToggle().getUserData().toString();
            if ("base64".equalsIgnoreCase(resultType)) {
                resultArea.setText(Base64.getEncoder().encodeToString(result));
            } else if ("hex".equalsIgnoreCase(resultType)) {
                resultArea.setText(HexFormat.of().formatHex(result).toUpperCase());
            } else {
                resultArea.setText(new String(result));
            }
        } catch (Exception e) {
            resultArea.setText("解密失败：" + e.getMessage());
        }
    }

    public void clear(ActionEvent actionEvent) {
        keyText.setText("");
        plainText.setText("");
        resultArea.setText("");
    }

    public void copy(ActionEvent actionEvent) {
        copy(resultArea.getText());
    }

    public void upload(ActionEvent actionEvent) {
    }

    public void changeType(ActionEvent actionEvent) {
        String type = typeGroup.getSelectedToggle().getUserData().toString();
        if ("AES".equalsIgnoreCase(type) || "DES3".equalsIgnoreCase(type) || "Twofish".equalsIgnoreCase(type)) {
            keyText.setPromptText("密钥长度为 16 或 24 或 32 字节");
        } else if ("DES".equalsIgnoreCase(type)) {
            keyText.setPromptText("密钥长度为 8 字节");
        } else if ("RC2".equalsIgnoreCase(type)) {
            keyText.setPromptText("密钥长度为 1 字节到 128 字节");
        } else if ("RC4".equalsIgnoreCase(type)) {
            keyText.setPromptText("密钥长度为 1 字节到 256 字节");
        } else if ("RC5".equalsIgnoreCase(type) || "RC6".equalsIgnoreCase(type)) {
            keyText.setPromptText("密钥最小长度为 1 字节");
        } else if ("Blowfish".equalsIgnoreCase(type)) {
            keyText.setPromptText("密钥长度为 4 字节到 56字节");
        } else if ("SM4".equalsIgnoreCase(type)) {
            keyText.setPromptText("密钥长度为 16 字节");
        }
        if ("RC4".equalsIgnoreCase(type)) {
            // RC4类型下不需要模式和填充
            modeHBox.setVisible(false);
            modeHBox.setManaged(false);
            paddingHBox.setVisible(false);
            paddingHBox.setManaged(false);
        } else {
            modeHBox.setVisible(true);
            modeHBox.setManaged(true);
            paddingHBox.setVisible(true);
            paddingHBox.setManaged(true);
        }
        keyText.setText("");
        changeMode(actionEvent);
    }

    public void changeMode(ActionEvent actionEvent) {
        String type = typeGroup.getSelectedToggle().getUserData().toString();
        String mode = modeGroup.getSelectedToggle().getUserData().toString();
        if ("ECB".equalsIgnoreCase(mode) || "RC4".equalsIgnoreCase(type)) {
            ivBox.setManaged(false);
            ivBox.setVisible(false);
            ivText.setText("");
            ivText.setPromptText("");
        } else {
            ivBox.setManaged(true);
            ivBox.setVisible(true);
            ivText.setText("");
            if ("AES".equalsIgnoreCase(type) || "SM4".equalsIgnoreCase(type) || "RC5".equalsIgnoreCase(type) || "Twofish".equalsIgnoreCase(type)) {
                ivText.setPromptText("长度为16字节");
                ivText.setText("0000000000000000");
            } else if ("DES".equalsIgnoreCase(type) || "DES3".equalsIgnoreCase(type) || "RC2".equalsIgnoreCase(type) || "RC6".equalsIgnoreCase(type) || "Blowfish".equalsIgnoreCase(type)) {
                ivText.setPromptText("长度为8字节");
                ivText.setText("00000000");
            }
        }
    }

    public byte[] plain2Byte(String type, String plain) {
        if ("Base64".equalsIgnoreCase(type)) {
            return Base64.getDecoder().decode(plain);
        } else if ("Hex".equalsIgnoreCase(type)) {
            return HexFormat.of().parseHex(plain);
        }
        return plain.getBytes(StandardCharsets.UTF_8);
    }
}
